package com.edulify.modules.sitemap;
import com.redfin.sitemapgenerator.WebSitemapUrl;
import com.redfin.sitemapgenerator.WebSitemapGenerator;
import java.lang.ClassLoader;
import java.lang.InstantiationException;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.util.Set;
import org.reflections.Reflections;
import org.reflections.scanners.MethodAnnotationsScanner;
import play.Configuration;
import play.mvc.Call;
import scala.Function0;
import javax.inject.Inject;
public class AnnotationUrlProvider implements UrlProvider {
private Configuration configuration;
@Inject
public AnnotationUrlProvider(Configuration configuration) {
this.configuration = configuration;
}
@Override
public void addUrlsTo(WebSitemapGenerator generator) {
String baseUrl = configuration.getString("sitemap.baseUrl");
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Reflections reflections = new Reflections("controllers", new MethodAnnotationsScanner());
Set<Method> actions = reflections.getMethodsAnnotatedWith(SitemapItem.class);
for(Method method : actions) {
String actionUrl = actionUrl(classLoader, method);
SitemapItem annotation = method.getAnnotation(SitemapItem.class);
if(annotation != null) {
WebSitemapUrl url = webSitemapUrl(baseUrl, actionUrl, annotation);
generator.addUrl(url);
}
}
}
private WebSitemapUrl webSitemapUrl(String baseUrl, String actionUrl, SitemapItem annotation) {
try {
return new WebSitemapUrl.Options(String.format("%s%s", baseUrl, actionUrl))
.changeFreq(annotation.changefreq())
.priority(annotation.priority())
.build();
} catch(MalformedURLException ex) {
play.Logger.error("MalformedURLException: ", ex);
}
return null;
}
private String actionUrl(ClassLoader classLoader, Method method) {
String itemUrl = "";
try {
String className = method.getDeclaringClass().getSimpleName();
String methodName = method.getName();
Class<?> clazz = classLoader.loadClass(String.format("controllers.Reverse%s", className));
Method reverseMethod = clazz.getMethod(methodName);
Class<?> routesPrefixClazz = classLoader.loadClass("router.RoutesPrefix");
Method byNamePrefixMethod = routesPrefixClazz.getMethod("byNamePrefix");
Call call = (Call) reverseMethod.invoke(clazz.getConstructor(Function0.class).newInstance(byNamePrefixMethod.invoke(routesPrefixClazz)));
itemUrl = call.url();
} catch (ClassNotFoundException ex) {
play.Logger.error("Package controllers does not have such class", ex);
} catch (NoSuchMethodException ex) {
play.Logger.error("Method not exists", ex);
} catch (IllegalAccessException ex) {
play.Logger.error("Method is not visible", ex);
} catch (InstantiationException ex) {
play.Logger.error("Reverse class could not be instantiated", ex);
} catch (InvocationTargetException ex) {
play.Logger.error("No instance of reverse class to call method", ex);
}
return itemUrl;
}
}